home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / pmpsrc11.zip / AX25SUBR.C < prev    next >
Text File  |  1991-07-30  |  6KB  |  293 lines

  1. /*
  2.     ax25subr.c -- General AX.25 subroutines
  3.  
  4.   Poor Man's Packet (PMP)
  5.   Copyright (c) 1991 by Andrew C. Payne    All Rights Reserved.
  6.  
  7.   Permission to use, copy, modify, and distribute this software and its
  8.   documentation without fee for NON-COMMERCIAL AMATEUR RADIO USE ONLY is hereby
  9.   granted, provided that the above copyright notice appear in all copies.
  10.   The author makes no representations about the suitability of this software
  11.   for any purpose.  It is provided "as is" without express or implied warranty.
  12.  
  13.     Andrew C. Payne
  14. */
  15. /* ----- Includes ------ */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <ctype.h>
  19. #include <string.h>
  20. #include <alloc.h>
  21. #include <bios.h>
  22. #include <mem.h>
  23. #include <ctype.h>
  24. #include "pmp.h"
  25.  
  26. /* ----- Address Manipulation ----- */
  27.  
  28. /* SetAX25Addr(addr,s)
  29.     Given a string s in the form 'N8KEI-3', converts to ax25_addr format.
  30.     Returns TRUE if error.
  31. */
  32. int SetAX25Addr(struct ax25_addr *a, char *s)
  33. {
  34.     struct ax25_addr    t;
  35.     int    i;
  36.  
  37. /* check for empty string */
  38.     if(*s == NULL)
  39.         return TRUE;
  40.  
  41.     for(i=0; i<MAXCLEN; i++) {
  42.         if(*s && *s != '-' && !isspace(*s))
  43.             t.call[i] = toupper(*s++) << 1;
  44.         else
  45.             t.call[i] = ' ' << 1;    /* pad w/ spaces */
  46.     }
  47.  
  48.     if(i > MAXCLEN && *s && *s != '-')    /* call too long */
  49.         return TRUE;
  50.  
  51.     if(*s == '-') {
  52.         i = atoi(s+1);
  53.         if(i > 15)
  54.             return TRUE;        /* invalid ssid */
  55.     } else
  56.         i = 0;                /* default */
  57.  
  58.     t.ssid = 0x60 | (i << 1);
  59.  
  60. /* all is well, copy it into 'a' */
  61.     memcpy(a,&t,sizeof(struct ax25_addr));
  62.     return FALSE;
  63. }
  64.  
  65. /* GetAX25Addr(addr)
  66.     Given a pointer to an ax25_addr record, returns an ASCII string of
  67.     the address in human readable form:  'N8KEI-3'
  68. */
  69. char *GetAX25Addr(struct ax25_addr *a)
  70. {
  71.     static    char    s[MAXCLEN+5];
  72.     char    *p;
  73.     char    c;
  74.     int    i;
  75.  
  76. /* translate callsign */
  77.     p = s;
  78.     for(i=0; i<MAXCLEN; i++) {
  79.         c = (a->call[i] >> 1) & 0x7f;
  80.         if(c == ' ')
  81.             break;
  82.         else
  83.             *p++ = c;
  84.     }
  85.  
  86. /* copy ssid if non-zero */
  87.     i = (a->ssid >> 1) & 0x0f;
  88.     if(i)
  89.         sprintf(p,"-%d",i);
  90.     else
  91.         *p = '\0';
  92.  
  93.     return s;        /* return pointer to string */
  94. }
  95.  
  96. /* CompAX25Addr(a1,a2)
  97.     Compares two AX.25 addresses.  Returns TRUE if they are not equal.
  98. */
  99. int CompAX25Addr(struct ax25_addr *a1, struct ax25_addr *a2)
  100. {
  101. /* compare the calls */
  102.     if(memcmp(a1->call,a2->call,sizeof(struct ax25_addr)-1))
  103.         return TRUE;
  104.  
  105. /* compare the SSIDs */
  106.     return (a1->ssid & 0x1e) != (a2->ssid & 0x1e);
  107. }
  108.  
  109. /* ----- Address/Path Parsing ----- */
  110.  
  111. /* SetAX25Path(s)
  112.     Given a path string in the form "KC3BQ-3 v W2CXM-1,WB2EMS-1",
  113.     and a pointer to a ax25_packet structure, sets the destination
  114.     address records.
  115.  
  116.     Returns TRUE if successful, FALSE if error.
  117. */
  118. int SetAX25Path(char *s, struct ax25_packet *a)
  119. {
  120.     char    *p;
  121.     char    t[80];
  122.     int    i;
  123.  
  124. /* extract the destination callsign */
  125.     p = extract(s,t);
  126.     if(SetAX25Addr(&a->dest,t))
  127.         return FALSE;
  128.  
  129. /* Is there a digi path? */
  130.     a->ndigis = i = 0;
  131.     if(*p == '\0')
  132.         return TRUE;    /* end of string, no digi path */
  133.  
  134.     p = extract(p,t);
  135.     if(*t != 'v')        /* expect VIA */
  136.         return FALSE;
  137.  
  138. /* extract digi path */
  139.     while(*p && i < MAXDIGIS) {
  140.         p = extract(p,t);
  141.         if(SetAX25Addr(a->digis+i,t))
  142.             return FALSE;
  143.  
  144.         i++;
  145.     }
  146.  
  147.     a->ndigis = i;
  148.     return i < MAXDIGIS;
  149. }
  150.  
  151. /* GetAX25Path(*packet)
  152.     Given a pointer to a level 2 packet, parses, and returns a pointer to
  153.     a human readable string in the form:
  154.  
  155.     "N8KEI [via WB2EMS]"
  156. */
  157. char *GetAX25Path(struct ax25_packet *p)
  158. {
  159.     static char    s[80];
  160.     int    i;
  161.     struct ax25_addr    *ad;
  162.  
  163. /* copy in the destination call */
  164.     strcpy(s,GetAX25Addr(&p->dest));
  165.  
  166. /* copy in the digi path */
  167.     if(i = p->ndigis) {
  168.         strcat(s," [via ");
  169.         strcat(s,GetAX25Addr(p->digis));
  170.         ad = p->digis + 1;
  171.         while(i > 1) {
  172.             strcat(s,",");
  173.             strcat(s,GetAX25Addr(ad++));
  174.             i--;
  175.         }
  176.         strcat(s,"]");
  177.     }
  178.  
  179.     return s;
  180. }
  181.  
  182. /* ----- Reverse Path ----- */
  183.  
  184. /* ReversePath(p1,p2)
  185.     Given two AX.25 Level 2 packets, constructs the path in p1 as the
  186.     reverse of the path in p2.
  187. */
  188. void ReversePath(struct ax25_packet *p1, struct ax25_packet *p2)
  189. {
  190.     int    i;
  191.  
  192.     memcpy(&p1->dest,&p2->source,sizeof(struct ax25_addr));
  193.     memcpy(&p1->source,&p2->dest,sizeof(struct ax25_addr));
  194.  
  195.     if(p1->ndigis = p2->ndigis) {
  196.         for(i=0; i<p2->ndigis; i++)
  197.             memcpy(p1->digis+i,p2->digis+(p2->ndigis - i - 1),
  198.                 sizeof(struct ax25_addr));
  199.     }
  200. }
  201.  
  202. /* ----- AX25 Packet Transmission ----- */
  203.  
  204. /* FrameType(control)
  205.     Given the control byte, returns the type of the frame.
  206. */
  207. int FrameType(byte c)
  208. {
  209.     if(!(c & 1))
  210.         return I;        /* Information */
  211.  
  212.     if(c & 2)
  213.         return c & ~PF;        /* U frames, strip PF */
  214.     else
  215.         return c & 0xf;        /* S frames */
  216. }
  217.  
  218. /* CmdResp(p)
  219.     Given a pointer to a level1 packet, returns the command/response
  220.     type.
  221. */
  222. int CmdResp(struct ax25_level1 *p)
  223. {
  224.     byte     *d;
  225.  
  226.     d = p->data;
  227.  
  228. /* figure out control/response bits */
  229.     if(d[MAXCLEN + sizeof(struct ax25_addr)] & 0x80) {
  230.         if(d[MAXCLEN] & 0x80)
  231.             return UNKNOWN;
  232.         else
  233.             return RESPONSE;
  234.     } else {
  235.         if(d[MAXCLEN] & 0x80)
  236.             return COMMAND;
  237.         else
  238.             return UNKNOWN;
  239.     }
  240. }
  241.  
  242. /* ----- Beacon ----- */
  243.  
  244. /* SendBeacon()
  245.     Sends the beacon message in 'btext' to the destination/path in
  246.     'baddr'.
  247. */
  248. void SendBeacon(void)
  249. {
  250.     struct ax25_packet    *p;
  251.  
  252. /* allocate an ax25_packet structure */
  253.     if((p = malloc(sizeof(struct ax25_packet) + strlen(btext))) == NULL)
  254.         OutOfMemory();
  255.  
  256. /* build UI packet with beacon text */
  257.     memcpy(&p->source, &MyCall, sizeof(struct ax25_addr));
  258.     p->pid = PID_TEXT;
  259.     p->cont = UI;
  260.     SetAX25Path(baddr, p);
  261.     strcpy(p->data, btext);
  262.     p->dlen = strlen(btext);
  263.  
  264.     SendAX25(p);
  265.     free(p);
  266. }
  267.  
  268. /* StartBeacon()
  269.     If 'BeaconInt' is non-zero, starts the beacon timing interval.
  270. */
  271. void StartBeacon(void)
  272. {
  273.     if(BeaconInt)
  274.         BeaconEnd = BiosTime() + (BIOSSEC * BeaconInt);
  275.     else
  276.         BeaconEnd = 0;
  277. }
  278.  
  279. /* ----- Send Welcome message ----- */
  280.  
  281. /* SendWelcome()
  282.     Sends the welcome message specified in CTEXT to incoming connects.
  283. */
  284. void SendWelcome(void)
  285. {
  286.     int    i;
  287.  
  288.     if(nctexts) {
  289.         for(i=0; i<nctexts; i++)
  290.             LinkSend(ctext[i],strlen(ctext[i]));
  291.     }
  292. }
  293.